Objective-C Runtime 发表于 2017-02-08 | 分类于 iOS | | 阅读次数: Objective-C Runtime是提供Objective-C语言动态特性的运行时的库。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345/* Types */#if !OBJC_TYPES_DEFINED// 类方法typedef struct objc_method *Method;// 实例变量typedef struct objc_ivar *Ivar;// 分类typedef struct objc_category *Category;// 对象声明的属性typedef struct objc_property *objc_property_t;// objc_class结构体struct objc_class { Class isa OBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class super_class OBJC2_UNAVAILABLE; // 父类 const char *name OBJC2_UNAVAILABLE; // 类名 long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0 long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识 long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小 struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表 struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表 struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法缓存 struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表#endif } OBJC2_UNAVAILABLE;#endif#ifdef __OBJC__@class Protocol;#elsetypedef struct objc_object Protocol;#endif// 定义方法struct objc_method_description { SEL name; // 方法的名称 char *types; // 方法的参数类型};// 定义属性typedef struct { const char *name; // 属性名称 const char *value; // 属性值} objc_property_attribute_t;/* 实例方法 */// 返回指定对象的一个副本OBJC_EXPORT id object_copy(id obj, size_t size);// 释放指定对象内存 返回nilOBJC_EXPORT id object_dispose(id obj);// 返回对象的类OBJC_EXPORT Class object_getClass(id obj);// 设置对象的类OBJC_EXPORT Class object_setClass(id obj, Class cls);// 是否是类对象OBJC_EXPORT BOOL object_isClass(id obj);// 返回给定对象的类名OBJC_EXPORT const char *object_getClassName(id obj);// 返回指向给定对象分配的任何额外字节的指针OBJC_EXPORT void *object_getIndexedIvars(id obj);// 返回对象中实例变量的值OBJC_EXPORT id object_getIvar(id obj, Ivar ivar);// 设置对象中实例变量的值OBJC_EXPORT void object_setIvar(id obj, Ivar ivar, id value);// 在对象中设置实例变量的值 iOS 10 AVAILABLEOBJC_EXPORT void object_setIvarWithStrongDefault(id obj, Ivar ivar, id value);// 修改类实例的实例变量的值OBJC_EXPORT Ivar object_setInstanceVariable(id obj, const char *name, void *value);// 更改一个实例类中实例变量的值 iOS 10 AVAILABLEOBJC_EXPORT Ivar object_setInstanceVariableWithStrongDefault(id obj, const char *name, void *value);// 返回对象实例变量的值OBJC_EXPORT Ivar object_getInstanceVariable(id obj, const char *name, void **outValue);/* 类方法 */// 返回指定的类OBJC_EXPORT Class objc_getClass(const char *name);// 返回指定的元类OBJC_EXPORT Class objc_getMetaClass(const char *name);// 返回指定的类OBJC_EXPORT Class objc_lookUpClass(const char *name);// 返回指定的类OBJC_EXPORT Class objc_getRequiredClass(const char *name);// 返回已注册的类定义的列表OBJC_EXPORT int objc_getClassList(Class *buffer, int bufferCount);// 创建并返回一个指向所有已注册类的指针列表OBJC_EXPORT Class *objc_copyClassList(unsigned int *outCount);// 返回类的类名OBJC_EXPORT const char *class_getName(Class cls);// 是否是元类OBJC_EXPORT BOOL class_isMetaClass(Class cls);// 返回类的父类OBJC_EXPORT Class class_getSuperclass(Class cls);// 给类指定一个父类OBJC_EXPORT Class class_setSuperclass(Class cls, Class newSuper);// 返回类版本号OBJC_EXPORT int class_getVersion(Class cls);// 设置类版本号OBJC_EXPORT void class_setVersion(Class cls, int version);// 返回实例类的大小OBJC_EXPORT size_t class_getInstanceSize(Class cls);// 返回类中指定名称实例成员变量的信息OBJC_EXPORT Ivar class_getInstanceVariable(Class cls, const char *name);// 返回类成员变量的信息OBJC_EXPORT Ivar class_getClassVariable(Class cls, const char *name);// 返回整个成员变量列表OBJC_EXPORT Ivar *class_copyIvarList(Class cls, unsigned int *outCount);// 返回实例方法OBJC_EXPORT Method class_getInstanceMethod(Class cls, SEL name);// 返回类方法OBJC_EXPORT Method class_getClassMethod(Class cls, SEL name);// 返回类方法实现的指针OBJC_EXPORT IMP class_getMethodImplementation(Class cls, SEL name);// 返回类方法实现的指针OBJC_EXPORT IMP class_getMethodImplementation_stret(Class cls, SEL name);// 类实例是否响应指定的selectorOBJC_EXPORT BOOL class_respondsToSelector(Class cls, SEL sel);// 返回所有方法的数组OBJC_EXPORT Method *class_copyMethodList(Class cls, unsigned int *outCount);// 返回类是否实现指定的协议OBJC_EXPORT BOOL class_conformsToProtocol(Class cls, Protocol *protocol);// 返回类实现的协议列表OBJC_EXPORT Protocol * __unsafe_unretained*class_copyProtocolList(Class cls, unsigned int *outCount);// 返回指定的属性OBJC_EXPORT objc_property_t class_getProperty(Class cls, const char *name);// 返回属性列表OBJC_EXPORT objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount);// 返回指定变量布局OBJC_EXPORT const uint8_t *class_getIvarLayout(Class cls);// 返回指定弱引用的变量布局OBJC_EXPORT const uint8_t *class_getWeakIvarLayout(Class cls);// 添加方法 如果返回YES则添加成功OBJC_EXPORT BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);// 替代方法的实现OBJC_EXPORT IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types);// 添加变量OBJC_EXPORT BOOL class_addIvar(Class cls, const char *name, size_t size,uint8_t alignment, const char *types);// 添加协议OBJC_EXPORT BOOL class_addProtocol(Class cls, Protocol *protocol);// 添加属性OBJC_EXPORT BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount);// 替换属性OBJC_EXPORT void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount);// 设置变量布局OBJC_EXPORT void class_setIvarLayout(Class cls, const uint8_t *layout);// 设置弱属性的变量布局OBJC_EXPORT void class_setWeakIvarLayout(Class cls, const uint8_t *layout);// 通过CoreFoundation's自由连接。不能自己调用此方法OBJC_EXPORT Class objc_getFutureClass(const char *name);// 创建类实例OBJC_EXPORT id class_createInstance(Class cls, size_t extraBytes);// 在指定位置创建类实例OBJC_EXPORT id objc_constructInstance(Class cls, void *bytes);// 销毁类实例OBJC_EXPORT void *objc_destructInstance(id obj);// 创建新的类OBJC_EXPORT Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes);// 注册创建的类OBJC_EXPORT void objc_registerClassPair(Class cls);// 用于KVO观察者模式。 不能自己调用此方法OBJC_EXPORT Class objc_duplicateClass(Class original, const char *name, size_t extraBytes);// 销毁一个类及其相关联的类OBJC_EXPORT void objc_disposeClassPair(Class cls);// 返回方法的名称OBJC_EXPORT SEL method_getName(Method m);// 返回一个方法指针OBJC_EXPORT IMP method_getImplementation(Method m);// 返回描述方法的字符串OBJC_EXPORT const char *method_getTypeEncoding(Method m);// 返回方法接收参数的个数OBJC_EXPORT unsigned int method_getNumberOfArguments(Method m);// 返回描述方法返回类型的字符串OBJC_EXPORT char *method_copyReturnType(Method m);// 返回描述方法单个参数类型的字符串OBJC_EXPORT char *method_copyArgumentType(Method m, unsigned int index);// 返回一个描述方法返回类型OBJC_EXPORT void method_getReturnType(Method m, char *dst, size_t dst_len);// 返回描述方法单个参数类型OBJC_EXPORT void method_getArgumentType(Method m, unsigned int index, char *dst, size_t dst_len);// 返回指定方法的结构描述OBJC_EXPORT struct objc_method_description *method_getDescription(Method m);// 设置方法的指针地址OBJC_EXPORT IMP method_setImplementation(Method m, IMP imp);/** * 交换两个方法指针地址 * @note 交换原理如下: * \code * IMP imp1 = method_getImplementation(m1); * IMP imp2 = method_getImplementation(m2); * method_setImplementation(m1, imp2); * method_setImplementation(m2, imp1); * \endcode */OBJC_EXPORT void method_exchangeImplementations(Method m1, Method m2);// 返回实例变量的名称OBJC_EXPORT const char *ivar_getName(Ivar v);// 返回实例变量类型的字符串OBJC_EXPORT const char *ivar_getTypeEncoding(Ivar v);// 返回实例变量的偏移量OBJC_EXPORT ptrdiff_t ivar_getOffset(Ivar v);// 返回OBJC_EXPORT const char *property_getName(objc_property_t property);// 返回属性的属性字符串OBJC_EXPORT const char *property_getAttributes(objc_property_t property);// 返回属性的属性数组OBJC_EXPORT objc_property_attribute_t *property_copyAttributeList(objc_property_t property, unsigned int *outCount);// 返回指定属性名称的属性的值OBJC_EXPORT char *property_copyAttributeValue(objc_property_t property, const char *attributeName);// 返回协议的名称OBJC_EXPORT Protocol *objc_getProtocol(const char *name);// 返回runtime已知的所有协议的数组OBJC_EXPORT Protocol * __unsafe_unretained *objc_copyProtocolList(unsigned int *outCount);// 判断一个协议是否遵循了另一个协议OBJC_EXPORT BOOL protocol_conformsToProtocol(Protocol *proto, Protocol *other);// 判断两个协议是否相等OBJC_EXPORT BOOL protocol_isEqual(Protocol *proto, Protocol *other);// 返回协议的名称OBJC_EXPORT const char *protocol_getName(Protocol *p);// 返回执行协议指定方法结构的描述OBJC_EXPORT struct objc_method_description protocol_getMethodDescription(Protocol *p, SEL aSel, BOOL isRequiredMethod, BOOL isInstanceMethod);// 返回满足指定协议方法描述的数组OBJC_EXPORT struct objc_method_description *protocol_copyMethodDescriptionList(Protocol *p, BOOL isRequiredMethod, BOOL isInstanceMethod, unsigned int *outCount);// 返回指定协议的属性OBJC_EXPORT objc_property_t protocol_getProperty(Protocol *proto, const char *name, BOOL isRequiredProperty, BOOL isInstanceProperty);/** * 返回声明协议所需要的属性的数组. * @note Identical to * \code * protocol_copyPropertyList2(proto, outCount, YES, YES); * \endcode */OBJC_EXPORT objc_property_t *protocol_copyPropertyList(Protocol *proto, unsigned int *outCount);OBJC_EXPORT objc_property_t *protocol_copyPropertyList2(Protocol *proto, unsigned int *outCount, BOOL isRequiredProperty, BOOL isInstanceProperty)OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0);// 返回协议所采用的协议的数组OBJC_EXPORT Protocol * __unsafe_unretained *protocol_copyProtocolList(Protocol *proto, unsigned int *outCount);// 创建一个新的协议,添加到objc_registerProtocol方法中OBJC_EXPORT Protocol *objc_allocateProtocol(const char *name);// 注册新协议OBJC_EXPORT void objc_registerProtocol(Protocol *proto);// 添加一个方法到协议中,此协议必须正在建设中OBJC_EXPORT void protocol_addMethodDescription(Protocol *proto, SEL name, const char *types, BOOL isRequiredMethod, BOOL isInstanceMethod);// 把已经建设的协议添加到正在建设的协议中去OBJC_EXPORT void protocol_addProtocol(Protocol *proto, Protocol *addition);// 添加一个属性到协议中去,此协议必须正在建设中OBJC_EXPORT void protocol_addProperty(Protocol *proto, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount, BOOL isRequiredProperty, BOOL isInstanceProperty);// 返回所有加载在Objective-C框架和动态库上的名称OBJC_EXPORT const char **objc_copyImageNames(unsigned int *outCount);// 返回一个来自类动态库的名称OBJC_EXPORT const char *class_getImageName(Class cls);// 返回库中所有类的名称OBJC_EXPORT const char **objc_copyClassNamesForImage(const char *image,unsigned int *outCount);// 返回指定sel的方法的名称OBJC_EXPORT const char *sel_getName(SEL sel);// 注册一个Objective-C运行时系统的方法名称OBJC_EXPORT SEL sel_getUid(const char *str);// 注册一个sel方法,并映方法名称到sel中并返回sel值OBJC_EXPORT SEL sel_registerName(const char *str);// 判断两个sel是否相同OBJC_EXPORT BOOL sel_isEqual(SEL lhs, SEL rhs);// 当发现突变的foreach迭代过程中时插入编译器OBJC_EXPORT void objc_enumerationMutation(id obj);// 设置当前突变的处理程序OBJC_EXPORT void objc_setEnumerationMutationHandler(void (*handler)(id));// 设置函数调用objc_msgForwardOBJC_EXPORT void objc_setForwardHandler(void *fwd, void *fwd_stret);// 创建一个当调用此方法时调用指定块的函数指针OBJC_EXPORT IMP imp_implementationWithBlock(id block);// 返回一个使用imp_implementationWithBlock创建的与块相关的函数指针OBJC_EXPORT id imp_getBlock(IMP anImp);// 移除与函数指针相关联的块OBJC_EXPORT BOOL imp_removeBlock(IMP anImp);// 加载弱指针引用的对象并返回它OBJC_EXPORT id objc_loadWeak(id *location);// 存储_weak变量的新值OBJC_EXPORT id objc_storeWeak(id *location, id obj);// 设置关联OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);// 获取关联值OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key);// 移除关联对象OBJC_EXPORT void objc_removeAssociatedObjects(id object);// 发送一个具有简单返回值的消息到一个实例类上OBJC_EXPORT void objc_msgSend(void /* id self, SEL op, ... */ );// 发送一个具有结构返回值的消息到一个实例类上OBJC_EXPORT void objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ );// 发送一个具有返回数据结构值的消息到一个实例类上OBJC_EXPORT void objc_msgSend_stret(void /* id self, SEL op, ... */ );// 发送一个具有返回数据结构值的消息到一个实例父类上OBJC_EXPORT void objc_msgSendSuper_stret(void /* struct objc_super *super, SEL op, ... */ );// 发送一个具有返回浮点类型值的消息到一个实例类上OBJC_EXPORT void objc_msgSend_fpret(void /* id self, SEL op, ... */ );OBJC_EXPORT void objc_msgSend_fp2ret(void /* id self, SEL op, ... */ );// 调用指定方法的实现OBJC_EXPORT void method_invoke(void /* id receiver, Method m, ... */ );// 调用返回数据结构的指定方法的实现OBJC_EXPORT void method_invoke_stret(void /* id receiver, Method m, ... */ );// 关联策略typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) { OBJC_ASSOCIATION_ASSIGN = 0, // 表示弱引用关联,非线程安全,通常是数据类型 OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, // 表示强(strong)引用关联对象,非线程安全 OBJC_ASSOCIATION_COPY_NONATOMIC = 3, // 表示关联对象copy,非线程安全 OBJC_ASSOCIATION_RETAIN = 01401, // 表示强(strong)引用关联对象,是线程安全的 OBJC_ASSOCIATION_COPY = 01403 // 表示关联对象copy,是线程安全的};// 编码类型#define _C_ID '@' // 代表对象类型#define _C_CLASS '#' // 代表类对象 (Class)#define _C_SEL ':' // 代表方法selector (SEL)#define _C_CHR 'c' // 代表char类型#define _C_UCHR 'C' // 代表unsigned char类型#define _C_SHT 's' // 代表short类型#define _C_USHT 'S' // 代表unsigned short类型#define _C_INT 'i' // 代表int类型#define _C_UINT 'I' // 代表unsigned int类型#define _C_LNG 'l' // 代表long类型,在64位处理器上也是按照32位处理#define _C_ULNG 'L' // 代表unsigned long类型#define _C_LNG_LNG 'q' // 代表long long类型#define _C_ULNG_LNG 'Q' // 代表unsigned long long类型#define _C_FLT 'f' // 代表float类型#define _C_DBL 'd' // 代表double类型#define _C_BFLD 'b' //#define _C_BOOL 'B' // 代表C++中的bool或者C99中的_Bool#define _C_VOID 'v' // 代表void类型#define _C_UNDEF '?' // 代表未知类型#define _C_PTR '^' // 代表指针类型#define _C_CHARPTR '*' // 代表字符串类型 (char *)#define _C_ATOM '%' //#define _C_ARY_B '[' // 代表array#define _C_ARY_E ']'#define _C_UNION_B '(' // 代表UNION#define _C_UNION_E ')'#define _C_STRUCT_B '{' // 代表结构体#define _C_STRUCT_E '}'#define _C_VECTOR '!' // 代表矢量类型#define _C_CONST 'r' // 代表常量类型 例子1 Runtime123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384// 获取属性列表&&获取属性名称unsigned int count;objc_property_t *propertyList = class_copyPropertyList([self class], &count);for (int i = 0; i < count ; i++) { const char *propertyName = property_getName(propertyList[i]); NSString *str = [NSString stringWithUTF8String:propertyName]; NSLog(@"property_getName==%@",str);}// 获取方法列表&&获取方法名称Method *methodList = class_copyMethodList([self class], &count);for (int i = 0; i < count; i++) { Method method = methodList[i]; //获取方法的参数列表 int arguments = method_getNumberOfArguments(method); NSLog(@"method_getNumberOfArguments===%d",arguments); NSLog(@"method_getName===%@",NSStringFromSelector(method_getName(method)));}// 获取类成员变量列表&&获取成员变量名称Ivar *ivarList = class_copyIvarList([self class], &count);for (int i = 0; i < count; i++) { Ivar ivar = ivarList[i]; NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)]; NSLog(@"ivar_getName===%@",ivarName);}// 获取类协议列表&&获取协议名称__unsafe_unretained Protocol **protocolList = class_copyProtocolList([self class], &count);for (unsigned int i = 0; i < count; i++) { Protocol *protocol = protocolList[i]; NSString *protocolStr = [NSString stringWithUTF8String:protocol_getName(protocol)]; NSLog(@"protocol_getName===%@",protocolStr);}// 是不是元类BOOL isMetaClass = class_isMetaClass(self.class);NSLog(@"ViewController is the meta class? %d", isMetaClass);// 是不是类对象ViewController *obj = [ViewController new];BOOL isClass = object_isClass(obj);NSLog(@"ViewController is the class? %d", isClass);// 获取类名称const char *name = class_getName(self.class);NSLog(@"class_getName===%@",[NSString stringWithCString:name encoding:NSUTF8StringEncoding]);// 设置关联&&获取关联static char *key = "key";objc_setAssociatedObject(self, &key, @"hello world", OBJC_ASSOCIATION_COPY_NONATOMIC);NSString *associated = objc_getAssociatedObject(self, &key);NSLog(@"objc_getAssociatedObject===%@",associated);/*----------------------Method Swizzling------------------------*/// 获取实例方法Method originalMethod = class_getInstanceMethod([self class], @selector(original:));Method exchangeMethod = class_getInstanceMethod([self class], @selector(exchange:));// 获取方法指针IMP exchangeImp = method_getImplementation(exchangeMethod);IMP originalImp = method_getImplementation(originalMethod);// 获取描述方法的参数类型const char *originalType = method_getTypeEncoding(originalMethod);const char *exchangeType = method_getTypeEncoding(exchangeMethod);// 添加方法BOOL didAddMethod = class_addMethod([self class], @selector(original:), exchangeImp, exchangeType);if (didAddMethod) { // 替换方法 class_replaceMethod([self class], @selector(exchange:), originalImp, originalType);}else{ // Method Swizzling method_exchangeImplementations(exchangeMethod, originalMethod);}/*----------------------Method Swizzling------------------------*/ 例子2 Runtime message12345678910111213141516171819202122232425262728293031323334// 初始化 [[MsgSend1 alloc] init]; MsgSend1 *msg = ((MsgSend1 * (*)(id,SEL))objc_msgSend)((id)[MsgSend1 class], @selector(alloc)); msg = ((MsgSend1 * (*)(id,SEL))objc_msgSend)((id)msg, @selector(init)); // 发送无参无返回值消息 ((void (*)(id,SEL))objc_msgSend)((id)msg, @selector(noArgumentsAndNoReturnValue)); // 发送有参数无返回值得消息 ((void (*)(id,SEL,NSString *))objc_msgSend)((id)msg, @selector(hasArguments:),@"带参数但是无返回值"); // 带返回值不带参数消息 NSString *retValue = ((NSString * (*)(id,SEL))objc_msgSend)((id)msg,@selector(noArgumentsButReturnValue)); NSLog(@"%@",retValue); // 带参数带返回值消息 int returnValue = ((int (*)(id,SEL,NSString *,int))objc_msgSend)((id)msg,@selector(hasValue1:Value2:),@"参数",999); NSLog(@"return value is %d",returnValue); // 动态添加方法再调用 其中i代表返回类型int,@代表参数,:代表SEL class_addMethod(msg.class, NSSelectorFromString(@"cStyleFunc"), (IMP)cStyleFunc,"i@:"); returnValue = ((int (*)(id,SEL,const void *,const void *))objc_msgSend)((id)msg,NSSelectorFromString(@"cStyleFunc"),"one","two"); NSLog(@"return value is %d",returnValue); // 带返回浮点值的消息 //objc_msgSend //float returnFloatValue = ((float (*)(id,SEL))objc_msgSend)((id)msg,@selector(returnFloatType)); //objc_msgSend_fpret float returnFloatValue = ((float (*)(id,SEL))objc_msgSend_fpret)((id)msg,@selector(returnFloatType)); NSLog(@"return float is %f",returnFloatValue); // 带结构体返回值的消息 //objc_msgSend_stret CGRect frame = ((CGRect (*)(id,SEL))objc_msgSend_stret)((id)self,@selector(returnTypeIsStruct)); NSLog(@"return frame is %@",NSStringFromCGRect(frame));